package com.imooc.pan.server.modules.file.controller;

import com.google.common.base.Splitter;
import com.imooc.pan.core.constants.RPanConstants;
import com.imooc.pan.core.response.R;
import com.imooc.pan.core.utils.IdUtil;
import com.imooc.pan.server.common.utils.UserIdUtil;
import com.imooc.pan.server.modules.file.constants.FileConstants;
import com.imooc.pan.server.modules.file.context.*;
import com.imooc.pan.server.modules.file.converter.FileConverter;
import com.imooc.pan.server.modules.file.enums.DelFlagEnum;
import com.imooc.pan.server.modules.file.po.*;
import com.imooc.pan.server.modules.file.service.RPanFileService;
import com.imooc.pan.server.modules.file.service.RPanUserFileService;
import com.imooc.pan.server.modules.file.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Spliterators;
import java.util.stream.Collectors;

/**
 * @author hhb
 * @data 2024/6/8 15:19
 */
@RequestMapping
@RestController
@Validated
public class FileController {

    @Autowired
    private RPanUserFileService rPanUserFileService;

    @Autowired
    private FileConverter fileConverter;


    @ApiOperation(
            value = "查询用户文件信息",
            notes = "该接口提供了用户查询文件信息的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @GetMapping("files")
    public R<List<RPanUserFileVo>> files(
            @NotBlank(message = "父文件ID不能为空") @RequestParam(value = "parentId",required = false) String parentId,
            @RequestParam(value = "fileTypes",required = false,defaultValue = FileConstants.ALL_FILE_TYPE) String fileTypes){
        Long realParentId = IdUtil.decrypt(parentId);
        //文件类型列表
        List<Integer> fileTypesArray = null;
        if(!Objects.equals(fileTypes,FileConstants.ALL_FILE_TYPE)){
            fileTypesArray = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileTypes).stream().map(Integer::valueOf).collect(Collectors.toList());
        }
        QueryFileContext fileContext = new QueryFileContext();
        fileContext.setParentId(realParentId);
        fileContext.setFileTypeArray(fileTypesArray);
        fileContext.setUserId(UserIdUtil.get());
        fileContext.setDelFlag(DelFlagEnum.NO.getCode());
        List<RPanUserFileVo> result = rPanUserFileService.queryFileList(fileContext);
        return R.data(result);
    }


    @ApiOperation(
            value = "创建文件夹",
            notes = "该接口提供了创建文件夹的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/folder")
    public R<String> createFolder(@Validated @RequestBody CreateFolderPO createFolderPO){
        CreateFolderContext createFolderContext = fileConverter.createFolderPOToCreateFolderContext(createFolderPO);

        Long fileId = rPanUserFileService.createFolder(createFolderContext);
        return R.data(IdUtil.encrypt(fileId));
    }

    @ApiOperation(
            value = "文件重命名",
            notes = "该接口提供了文件重命名的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PutMapping("file")
    public R updateFilename(@Validated @RequestBody UpdateFilenamePO updateFilenamePO){
        UpdateFilenameContext updateFilenameContext = fileConverter.updateFilenamePOToUpdateFilenameContext(updateFilenamePO);
        rPanUserFileService.updateFilename(updateFilenameContext);
        return R.success();
    }

    @ApiOperation(
            value = "批量删除文件",
            notes = "该接口提供了批量删除文件的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @DeleteMapping("file")
    public R deleteFile(@Validated @RequestBody DeleteFilePO deleteFilePO){
        DeleteFileContext deleteFileContext = fileConverter.deleteFilePOToDeleteFileContext(deleteFilePO);
        String fileIds = deleteFilePO.getFileIds();
        List<Long> fileIdArray = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        deleteFileContext.setFileIdList(fileIdArray);
        rPanUserFileService.deleteFile(deleteFileContext);
        return R.success();
    }

    @ApiOperation(
            value = "文件秒传",
            notes = "该接口实现了文件秒传的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/sec-upload")
    public R secUpload(@Validated @RequestBody SecUploadFilePO secUploadFilePO){
        SecUploadFileContext secUploadFileContext = fileConverter.secUploadFilePOToSecUploadFileContext(secUploadFilePO);
        boolean success = rPanUserFileService.secUpload(secUploadFileContext);
        if(success){
            return R.success();
        }
        return R.fail("文件唯一标识不存在，请手动上传文件");
    }



    @ApiOperation(
            value = "单文件上传",
            notes = "该接口实现了单文件上传的功能",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/upload")
    public R upload(@Validated @RequestBody FileUploadPO fileUploadPO){
        FileUploadContext fileContext = fileConverter.fileUploadPOToFileUploadContext(fileUploadPO);
        rPanUserFileService.upload(fileContext);
        return R.success();
    }


    @ApiOperation(
            value = "文件分片上传",
            notes = "该接口实现了文件分片上传的功能",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/chunk-upload")
    public R<FileChunkUploadVo> chunkUpload(@Validated FileChunkUploadPO fileChunkUploadPO){
        FileChunkUploadContext fileChunkUploadContext = fileConverter.fileChunkUploadPOToFileChunkUploadContext(fileChunkUploadPO);
        FileChunkUploadVo vo = rPanUserFileService.chunkUpload(fileChunkUploadContext);
        return R.data(vo);
    }

    @ApiOperation(
            value = "查询用户已上传的分片列表",
            notes = "该接口实现了查询用户已上传的分片列表的功能",
            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @GetMapping("file/chunk-upload")
    public R<UploadChunksVO> getUploadChunksVO(@Validated QueryUploadChunksPO queryUploadChunksPO){
        QueryUploadChunksContext queryUploadChunksContext = fileConverter.queryUploadChunksPOToQueryUploadChunksContext(queryUploadChunksPO);
        UploadChunksVO vo = rPanUserFileService.getUploadChunksVO(queryUploadChunksContext);
        return R.data(vo);
    }


    @ApiOperation(
            value = "文件分片合并",
            notes = "该接口实现了文件分片合并的功能",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/merge")
    public R mergeFile(@Validated @RequestBody FileChunkMergePo fileChunkMergePo){
        FileChunkMergeContext context = fileConverter.fileChunkMergePoToFileChunkMergeContext(fileChunkMergePo);
        rPanUserFileService.mergeFile(context);
        return R.success();
    }


    @ApiOperation(
            value = "文件下载",
            notes = "该接口实现了文件下载的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
    )
    @GetMapping("file/download")
    public R download(@NotBlank(message = "文件ID不能为空") @RequestParam(value = "fileId",required = false) String fileId,
                      HttpServletResponse response){
        FileDownloadContext context = new FileDownloadContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setUserId(UserIdUtil.get());
        context.setHttpServletResponse(response);
        rPanUserFileService.download(context);
        return R.success();
    }

    @ApiOperation(
            value = "文件预览",
            notes = "该接口实现了文件预览的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
    )
    @GetMapping("file/preview")
    public R preview(@NotBlank(message = "文件ID不能为空") @RequestParam(value = "fileId",required = false) String fileId,
                      HttpServletResponse response){
        FilePreviewContext context = new FilePreviewContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setUserId(UserIdUtil.get());
        context.setHttpServletResponse(response);
        rPanUserFileService.preview(context);
        return R.success();
    }

    @ApiOperation(
            value = "查询文件夹树",
            notes = "该接口实现了查询文件夹树的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @GetMapping("file/folder/tree")
    public R<List<FolderTreeNodeVO>> getFolderTree(){
        QueryFolderTreeContext context = new QueryFolderTreeContext();
        List<FolderTreeNodeVO> result = rPanUserFileService.queryFolderTree(context);
        return R.data(result);
    }


    @ApiOperation(
            value = "文件转移",
            notes = "该接口实现了文件转移的功能",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/transfer")
    public R transferFile(@Validated @RequestBody TransferFilePO transferFilePO){
        String fileIds = transferFilePO.getFileIds();
        List<Long> fileIdList = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        TransferFileContext context = new TransferFileContext();
        context.setFileIdList(fileIdList);
        context.setUserId(UserIdUtil.get());
        context.setTargetParentId(IdUtil.decrypt(transferFilePO.getTargetParentId()));
        rPanUserFileService.transfer(context);
        return R.success();
    }


    @ApiOperation(
            value = "文件复制",
            notes = "该接口实现了文件复制的功能",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/copy")
    public R copy(@Validated @RequestBody CopyFilePO copyFilePO){
        String fileIds = copyFilePO.getFileIds();
        List<Long> fileIdList = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        CopyFileContext context = new CopyFileContext();
        context.setFileIdList(fileIdList);
        context.setUserId(UserIdUtil.get());
        context.setTargetParentId(IdUtil.decrypt(copyFilePO.getTargetParentId()));
        rPanUserFileService.copy(context);
        return R.success();
    }


    @ApiOperation(
            value = "文件搜索",
            notes = "该接口实现了文件搜索的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @PostMapping("file/search")
    public R<List<FileSearchResultVO>> search(@Validated FileSearchPO fileSearchPO){
        List<Integer> fileTypeArray = new ArrayList<>();
        if(!Objects.equals(fileSearchPO.getFileTypes(),FileConstants.ALL_FILE_TYPE)){
            fileTypeArray = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileSearchPO.getFileTypes()).stream().map(Integer::valueOf).collect(Collectors.toList());
        }
        FileSearchContext context = new FileSearchContext();
        context.setUserId(UserIdUtil.get());
        context.setKeyword(fileSearchPO.getKeyword());
        context.setFileTypeArray(fileTypeArray);
        List<FileSearchResultVO> result = rPanUserFileService.search(context);
        return R.data(result);
    }


    @ApiOperation(
            value = "查询面包屑列表",
            notes = "该接口实现了查询面包屑列表的功能",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    @GetMapping("file/breadcrumbs")
    public R<List<BreadCurmbVO>> getBreadcurms(@NotBlank(message = "文件ID不能为空")
                                               @RequestParam(value = "fileId",required = false) String fileId){
        QueryBreadCurmsContext context = new QueryBreadCurmsContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setUserId(UserIdUtil.get());
        List<BreadCurmbVO> result = rPanUserFileService.getBreadcurmbs(context);
        return R.data(result);
    }






}
